/*
 * SignatureTestCase.java
 * JMUnit based test
 *
 * Created on 2008-sep-26, 16:07:47
 */

package com.ericsson.nfc.signing.record;

import java.io.UnsupportedEncodingException;
//#ifdef MyJSR257
//# import my.javax.microedition.contactless.ndef.NDEFMessage;
//# import my.javax.microedition.contactless.ndef.NDEFRecord;
//# import my.javax.microedition.contactless.ndef.NDEFRecordType;
//#else
import javax.microedition.contactless.ndef.NDEFMessage;
import javax.microedition.contactless.ndef.NDEFRecord;
import javax.microedition.contactless.ndef.NDEFRecordType;
//#endif
import jmunit.framework.cldc11.AssertionFailedException;
import jmunit.framework.cldc11.TestCase;

/**
 * @author emarkki
 */
public class SignatureTestCase extends TestCase {

    private static final NDEFRecordType EXTERNAL_SIGREC = new NDEFRecordType(NDEFRecordType.EXTERNAL_RTD, "urn:nfc:ext:ericsson.com:SigRec123");
    
    public SignatureTestCase() {
        // The first parameter of inherited constructor is the number of test cases
        super(31, "RecordTestCase");
    }            

    public void test(int testNumber) throws Throwable {
        
        System.out.println("\n\n------ T E S T  " + testNumber + "  -------");
        
        switch (testNumber) {
            case 0:
                test1();
                break;
            case 1:
                testRecordTypeConstructed();
                break;
            case 2:
                testRecordTypeParsed();
                break;
            case 3:
                testIgnoreRFU();
                break;
            case 4:
                testVersionParsed();
                break;
            case 5:
                testIgnoreVersion();
                break;
            case 6:
                testURIParsed();
                break;
            case 7:
                testSignatureTypeParsed();
                break;
            case 8:
                testSignatureTypeConstructedAndParsed();
                break;
            case 9:
                testGetCertificates();
                break;
            case 10:
                testSignatureLengthParsed();
                break;
            case 11:
                testSignatureParsed();
                break;
            case 12:
                testSignatureConstructedAndParsed();
                break;
            case 13:
                testMarker();
                break;
            case 14:
                testCertificateSubFieldParsed();
                break;
            case 15:
                testCertificateGetBytes();
                break;
            case 16:
                testGetSignatureURIParsed();
                break;
            case 17:
                testParseNDEF();
                break;
            case 18:
                testGetCertificateURIParsed();
                break;
            case 19:
                testGetCertificateURIConstructedAndParsed();
                break;
            case 20:
                testURIRecordConstructedAndParsed();
                break;
            case 21:
                testURIRecordParsed();
                break;
            case 22:
                testURIRecordConstructed();
                break;
            case 23:
                testURIRecordEquals();
                break;
            case 24:
                testSignatureRecordEquals();
                break;
            case 25:
                testCreateSignaturRecordWithURIs();
                break;
            case 26:
                testGetSignatureURIConstructedAndParsed();
                break;
            case 27:
                testGetCertificatesConstructedAndParsed();
                break;
            case 28:
                testGetSignatureURIParsed();
                break;
            case 29:
                testDontIgnoreRFUForExternalRTD();

                break;
            case 30:
                testToNDEFRecordWithExternalType();
                break;
            case 31:
                
                break;
            case 32:
                
                break;
            default:
                break;
        }
    }

    /**
     * Dummy test
     */
    public void test1() throws AssertionFailedException {
        
        System.out.println("test1");
        
    }

    private void testRecordTypeConstructed() throws AssertionFailedException {
        System.out.println("testRecordTypeConstructed");

        SignatureRecord r1 = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0]));

        assertEquals("a", new NDEFRecordType(NDEFRecordType.NFC_FORUM_RTD, "urn:nfc:wkt:Sig"), r1.toNDEFRecord().getRecordType());
        assertEquals("b", new NDEFRecordType(NDEFRecordType.NFC_FORUM_RTD, "urn:nfc:wkt:Sig"), new SignatureRecord().toNDEFRecord().getRecordType());
    }

    private void testRecordTypeParsed() throws AssertionFailedException {
        try {
            System.out.println("testRecordTypeParsed");

            SignatureRecord record = new SignatureRecord(new NDEFMessage(TestData.msgSpUrlSig1, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1));

            assertEquals(new NDEFRecordType(NDEFRecordType.NFC_FORUM_RTD, "urn:nfc:wkt:Sig"), record.toNDEFRecord().getRecordType());
        } catch (InvalidSignatureRecord ex) {
            fail(ex.getMessage());
        }
    }
    
    /**
     * "...a Signature or Certificate type value defined as RFU MUST ignore 
     * the Signature record in which the value was contained and consider the 
     * signature as invalid"
     */
    private void testIgnoreRFU() throws AssertionFailedException {
        System.out.println("testIgnoreRFU");

        // Construct
        try {
            SignatureRecord r1 = new SignatureRecord(new SignatureField(0x05, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0]));
            NDEFRecord record = r1.toNDEFRecord();
            fail("Accepted r1");
        } catch(IllegalArgumentException ex) {}

        try {
            SignatureRecord r2 = new SignatureRecord(new SignatureField(0x11, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0]));
            NDEFRecord record = r2.toNDEFRecord();
            fail("Accepted r2");
        } catch(IllegalArgumentException ex) {}

        try {
            SignatureRecord r3 = new SignatureRecord(new SignatureField(0x7f, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0]));
            NDEFRecord record = r3.toNDEFRecord();
            fail("Accepted r3");
        } catch(IllegalArgumentException ex) {}

        try {
            SignatureRecord r4 = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(0x02, new CertificateBytes[0]));
            NDEFRecord record = r4.toNDEFRecord();
            fail("Accepted r4");
        } catch(IllegalArgumentException ex) {}
        try {
            SignatureRecord r5 = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(0x05, new CertificateBytes[0]));
            NDEFRecord record = r5.toNDEFRecord();
            fail("Accepted r5");
        } catch(IllegalArgumentException ex) {}
        try {
            SignatureRecord r6 = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(0x07, new CertificateBytes[0]));
            NDEFRecord record = r6.toNDEFRecord();
            fail("Accepted r6");
        } catch(IllegalArgumentException ex) {}
        try {
            SignatureRecord r7 = new SignatureRecord(new SignatureField(0x14, "SIGNATURE".getBytes()), new CertificateField(0x06, new CertificateBytes[0]));
            NDEFRecord record = r7.toNDEFRecord();
            fail("Accepted r7");
        } catch(IllegalArgumentException ex) {}

        // Parse
        try {
            byte[] bytes = new byte[TestData.msgSpUrlSig1.length];
            System.arraycopy(TestData.msgSpUrlSig1, 0, bytes, 0, TestData.msgSpUrlSig1.length);
            bytes[46] &= 0x80;
            bytes[46] |= 0x05;
            SignatureRecord r1 = new SignatureRecord(new NDEFMessage(bytes, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1));
            fail("Accepted r1 b");
        } catch(InvalidSignatureRecord ex) {}

        try {
            byte[] bytes = new byte[TestData.msgSpUrlSig1.length];
            System.arraycopy(TestData.msgSpUrlSig1, 0, bytes, 0, TestData.msgSpUrlSig1.length);
            bytes[46] &= 0x80;
            bytes[46] |= 0x11;
            SignatureRecord r1 = new SignatureRecord(new NDEFMessage(bytes, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1));
            fail("Accepted r2 b");
        } catch(InvalidSignatureRecord ex) {}

        try {
            byte[] bytes = new byte[TestData.msgSpUrlSig1.length];
            System.arraycopy(TestData.msgSpUrlSig1, 0, bytes, 0, TestData.msgSpUrlSig1.length);
            bytes[46] &= 0x80;
            bytes[46] |= 0x7f;
            SignatureRecord r1 = new SignatureRecord(new NDEFMessage(bytes, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1));
            fail("Accepted r3 b");
        } catch(InvalidSignatureRecord ex) {}

        try {
            byte[] bytes = new byte[TestData.msgSpUrlSig1.length];
            System.arraycopy(TestData.msgSpUrlSig1, 0, bytes, 0, TestData.msgSpUrlSig1.length);
            bytes[113] &= 0x70;
            bytes[113] |= (0x02 << 4);
            SignatureRecord r1 = new SignatureRecord(new NDEFMessage(bytes, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1));
            fail("Accepted r4 b");
        } catch(InvalidSignatureRecord ex) {}
        try {
            byte[] bytes = new byte[TestData.msgSpUrlSig1.length];
            System.arraycopy(TestData.msgSpUrlSig1, 0, bytes, 0, TestData.msgSpUrlSig1.length);
            bytes[113] &= 0x70;
            bytes[113] |= (0x05 << 4);
            SignatureRecord r1 = new SignatureRecord(new NDEFMessage(bytes, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1));
            fail("Accepted r5 b");
        } catch(InvalidSignatureRecord ex) {}
        try {
            byte[] bytes = new byte[TestData.msgSpUrlSig1.length];
            System.arraycopy(TestData.msgSpUrlSig1, 0, bytes, 0, TestData.msgSpUrlSig1.length);
            bytes[113] &= 0x70;
            bytes[113] |= (0x07 << 4);
            SignatureRecord r1 = new SignatureRecord(new NDEFMessage(bytes, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1));
            fail("Accepted r6 b");
        } catch(InvalidSignatureRecord ex) {}
        try {
            byte[] bytes = new byte[TestData.msgSpUrlSig1.length];
            System.arraycopy(TestData.msgSpUrlSig1, 0, bytes, 0, TestData.msgSpUrlSig1.length);
            bytes[45] &= 0x80;
            bytes[45] |= 0x14;
            bytes[113] &= 0x70;
            bytes[113] |= (0x06 << 4);
            SignatureRecord r1 = new SignatureRecord(new NDEFMessage(bytes, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1));
            fail("Accepted r7 b");
        } catch(InvalidSignatureRecord ex) {}

    }

    private void testVersionParsed() throws AssertionFailedException {
        System.out.println("testGetVersion");

        SignatureRecord r1 = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0]));
        assertEquals(0x01, r1.getVersion());

        SignatureRecord r2 = new SignatureRecord();
        assertEquals(0x01, r2.getVersion());
    }

    private void testIgnoreVersion() throws AssertionFailedException {
        System.out.println("testIgnoreVersion");
        try {
            byte[] bytes = new byte[TestData.msgSpUrlSig1.length];
            System.arraycopy(TestData.msgSpUrlSig1, 0, bytes, 0, TestData.msgSpUrlSig1.length);
            bytes[45] = 0x02;

            SignatureRecord r1 = new SignatureRecord(new NDEFMessage(bytes, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1));
            fail("accepted version != 0x01");
        } catch (InvalidSignatureRecord ex) {}

        // TODO: Do this for marker to
//        try {
//            byte[] bytes = new byte[msgSpUrlSig1.length];
//            System.arraycopy(msgSpUrlSig1, 0, bytes, 0, msgSpUrlSig1.length);
//            bytes[45] = 0x02;
//
//            SignatureRecord r1 = new SignatureRecord(bytes, 45);
//            fail("accepted version != 0x01");
//        } catch (InvalidSignatureRecord ex) {}
    }

    private void testURIParsed() throws AssertionFailedException {
        System.out.println("testURIPresentParsed");

        try {
            assertTrue("No Signature URI in this record",
                    null == new SignatureRecord(new NDEFMessage(TestData.msgSpUrlSig1, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1)).getSignatureField().getUri());

            // TODO: Add code to test other records here

        } catch (InvalidSignatureRecord ex) {
            ex.printStackTrace();
            fail(ex.getMessage());
        }
    }

    private void testSignatureTypeParsed() throws AssertionFailedException {
        System.out.println("testSignatureTypeParsed");

        try {
            assertEquals("Type RSSA_PSS", SignatureField.RSASSA_PSS,
                    new SignatureRecord(new NDEFMessage(TestData.msgSpUrlSig1, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1)).getSignatureField().getType());

            // TODO: Add code to test other records here

        } catch (InvalidSignatureRecord ex) {
            ex.printStackTrace();
            fail(ex.getMessage());
        }
    }

    private void testSignatureTypeConstructedAndParsed() throws AssertionFailedException {
        try {
            System.out.println("testSignatureTypeConstructedAndParsed");

            assertEquals("Signature type 0",
                    0, new SignatureRecord(new SignatureRecord(new SignatureField(0, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getType());

            assertEquals("Signature type 1",
                    1, new SignatureRecord(new SignatureRecord(new SignatureField(1, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getType());

            assertEquals("Signature type 2",
                    2, new SignatureRecord(new SignatureRecord(new SignatureField(2, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getType());

            assertEquals("Signature type 3",
                    3, new SignatureRecord(new SignatureRecord(new SignatureField(3, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getType());

            assertEquals("Signature type 4",
                    4, new SignatureRecord(new SignatureRecord(new SignatureField(4, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getType());

        } catch (InvalidSignatureRecord ex) {
            fail(ex.getMessage());
        }
    }

    private void testGetCertificates() throws AssertionFailedException {
        System.out.println("testGetCertificates");
        try {
            assertEquals("1 certificate a", 1, new SignatureRecord(new NDEFMessage(TestData.msgSpUrlSig1, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1)).getCertificateField().getChain().length);

            assertEquals("0 certificate a", 0, new SignatureRecord(new SignatureField(0, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0])).getCertificateField().getChain().length);
            assertEquals("1 certificate b", 1, new SignatureRecord(new SignatureField(0, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[]{new CertificateBytes(new byte[]{})})).getCertificateField().getChain().length);
            assertEquals("5 certificates", 5, new SignatureRecord(new SignatureField(0, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[]{new CertificateBytes(new byte[]{}),new CertificateBytes(new byte[]{}),new CertificateBytes(new byte[]{}),new CertificateBytes(new byte[]{}),new CertificateBytes(new byte[]{})})).getCertificateField().getChain().length);

            assertTrue("null certificates in marker", null == new SignatureRecord().getCertificateField().getChain());

        } catch (InvalidSignatureRecord ex) {
            ex.printStackTrace();
            fail(ex.getMessage());
        }
    }

    private void testSignatureLengthParsed() throws AssertionFailedException {
        System.out.println("testSignatureLengthParsed");
        try {
            assertEquals("Signature Length", 64,
                    new SignatureRecord(new NDEFMessage(TestData.msgSpUrlSig1, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1)).getSignatureField().getSignature().length);

            // TODO: Add code to test other records here

        } catch (InvalidSignatureRecord ex) {
            ex.printStackTrace();
            fail(ex.getMessage());
        }
    }

    private void testSignatureParsed() throws AssertionFailedException {
        System.out.println("testSignatureParsed");
        try {
            assertTrue(Utils.equals(TestData.msgSpUrlSig1Signature, new SignatureRecord(new NDEFMessage(TestData.msgSpUrlSig1, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1)).getSignatureField().getSignature()));

            // TODO: Add code to test other records here

        } catch (InvalidSignatureRecord ex) {
            ex.printStackTrace();
            fail(ex.getMessage());
        }
    }

    /**
     * 12
     */
    private void testSignatureConstructedAndParsed() throws AssertionFailedException {
        try {
            System.out.println("testSignatureConstructedAndParsed");

            String sig0 = "";
            String sig1 = "S";
            String sig2 = "Signature 2";
            String sig3 = "Signature 333333333333333333333333333333333333333333333.";

            assertTrue("Signature 0", Utils.equals(sig0.getBytes(), new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig0.getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getSignature()));
            assertTrue("Signature 1", Utils.equals(sig1.getBytes(), new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig1.getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getSignature()));
            assertTrue("Signature 2", Utils.equals(sig2.getBytes(), new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig2.getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getSignature()));
            assertTrue("Signature 3", Utils.equals(sig3.getBytes(), new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig3.getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getSignature()));
            assertTrue("Signature mark", new SignatureRecord(new SignatureRecord().toNDEFRecord()).getSignatureField().getSignature() == null);

            // 65 bytes
            {
                byte[] sig = new byte[65];
                fill(sig);
                assertTrue("Signature 4", Utils.equals(sig, new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getSignature()));
            }

            // 127 bytes
            {
                byte[] sig = new byte[127];
                fill(sig);
                assertTrue("Signature 5", Utils.equals(sig, new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getSignature()));
            }

            // 128 bytes
            {
                byte[] sig = new byte[128];
                fill(sig);
                assertTrue("Signature 6", Utils.equals(sig, new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getSignature()));
            }

            // 256 bytes
            {
                byte[] sig = new byte[256];
                fill(sig);
                assertTrue("Signature 7", Utils.equals(sig, new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getSignature()));
            }

            // 257 bytes
            {
                byte[] sig = new byte[257];
                fill(sig);
                assertTrue("Signature 8", Utils.equals(sig, new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getSignature()));
            }

            // 512 bytes
            {
                byte[] sig = new byte[512];
                fill(sig);
                assertTrue("Signature 9", Utils.equals(sig, new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getSignature()));
            }

            // 1024 bytes
            {
                byte[] sig = new byte[1024];
                fill(sig);
                assertTrue("Signature 10", Utils.equals(sig, new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord()).getSignatureField().getSignature()));
            }

        } catch (InvalidSignatureRecord ex) {
            ex.printStackTrace();
            fail(ex.getMessage());
        }
    }

    private void fill(byte[] buffer) {
        for(int i = 0; i < buffer.length; i++) {
            buffer[i] = (byte)i;
        }
    }

    private void testMarker() throws AssertionFailedException {
        System.out.println("testMarker");

        byte[] sig = "SIGNATURE".getBytes();

        SignatureRecord nonMarker = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig), new CertificateField(CertificateField.X509, new CertificateBytes[0]));
        SignatureRecord marker = new SignatureRecord();

        assertFalse("Non marker not marker", nonMarker.isMarker());
        assertTrue("Marker is marker", marker.isMarker());

        assertTrue("marker URI_present == 0", marker.getSignatureField().getUri() == null);
        assertEquals("marker Signature_Type == 0", 0, marker.getSignatureField().getType());
        assertTrue("marker has no signature", marker.getSignatureField().getSignature() == null);
        assertTrue("marker has no signature URI", marker.getSignatureField().getUri() == null);
        assertTrue("marker has no certificate chain", marker.getCertificateField().getChain() == null);

        if(nonMarker.getSignatureField().getUri() == null && nonMarker.getSignatureField().getType() != 0) {
            System.out.println("signature: " + nonMarker.getSignatureField().getSignature().length);
            assertTrue("nonMarker contains signature", Utils.equals(sig, nonMarker.getSignatureField().getSignature()));
            assertTrue("nonMarker does not contain URI", nonMarker.getSignatureField().getUri() == null);
        }

        if(nonMarker.getSignatureField().getUri() != null && nonMarker.getSignatureField().getType() != 0) {
            assertTrue("nonMarker contains URI", nonMarker.getSignatureField().getUri() == null);
            assertTrue("nonMarker does not contain signature", nonMarker.getSignatureField().getSignature() == null);
        }

        if(nonMarker.getSignatureField().getUri() != null) {
            assertTrue("Signature Type != 0", nonMarker.getSignatureField().getType() != 0);
        }

    }

    private void testCertificateSubFieldParsed() throws AssertionFailedException {
        try {
            System.out.println("testCertificateSubFieldParsed");

            byte[] certificate = "**CERTIFICATE**".getBytes();

            SignatureRecord r1 = new SignatureRecord(new NDEFMessage(TestData.msgSpUrlSig1, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1));
            CertificateBytes[] certs1 = r1.getCertificateField().getChain();

            assertEquals("msgSpUrlSig1 certs.length", 1, certs1.length);
            assertTrue("msgSpUrlSig1 certificate", Utils.equals(certificate, certs1[0].getBytes()));
        } catch (InvalidSignatureRecord ex) {
            ex.printStackTrace();
        }
    }

    private void testCertificateGetBytes() throws AssertionFailedException {
        System.out.println("testCertificateGetBytes");

        assertTrue("1 byte", Utils.equals(new byte[]{(byte)0xA}, new CertificateBytes(new byte[]{(byte)0xA}).getBytes()));
        assertTrue("2 bytes", Utils.equals(new byte[]{(byte)0xA, (byte)0xB}, new CertificateBytes(new byte[]{(byte)0xA,(byte)0xB}).getBytes()));
        assertTrue("0 bytes", Utils.equals(new byte[0], new CertificateBytes(new byte[]{}).getBytes()));
    }

    private void testGetSignatureURIParsed() throws AssertionFailedException {
        try {
            System.out.println("testGetSignatureURIConstrunctedAndParsed");

            SignatureRecord r1 = new SignatureRecord(new NDEFMessage(TestData.msgSpUrlSig1, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1));
            assertTrue("r1.signatureUri == null", r1.getSignatureField().getUri() == null);

            // TODO: Add tests for other records

        } catch (InvalidSignatureRecord ex) {
            ex.printStackTrace();
        }
    }

    private void testGetCertificateURIParsed() throws AssertionFailedException {
        try {
            System.out.println("testGetCertificateURIParsed");

            URIRecord uri1 = new URIRecord(new NDEFMessage(TestData.msgSpUrlSig1CertificateUri, 0).getRecord(0).getPayload(), 0);

            SignatureRecord r1 = new SignatureRecord(new NDEFMessage(TestData.msgSpUrlSig1, 0).getRecord(0).getNestedNDEFMessage(0).getRecord(1));

            System.out.println("uri1: " + new String(TestData.msgSpUrlSig1CertificateUri));
            System.out.println("r1: " + new String(r1.getCertificateField().getUri().toNDEFRecord().toByteArray()));

            assertEquals(uri1, r1.getCertificateField().getUri());

        } catch (InvalidSignatureRecord ex) {
            ex.printStackTrace();
            fail(ex.getMessage());
        }
    }

    /**
     * 18
     */
    private void testGetCertificateURIConstructedAndParsed() throws AssertionFailedException {
        try {
            System.out.println("testGetCertificateURIConstructedAndParsed");

            URIRecord uri1 = new URIRecord("http://www.kth.se");

            assertEquals(uri1, new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0], uri1)).toNDEFRecord()).getCertificateField().getUri());
        } catch (InvalidSignatureRecord ex) {
            ex.printStackTrace();
            fail(ex.getMessage());
        }
    }

    private void testURIRecordConstructedAndParsed() throws AssertionFailedException {
        System.out.println("testURIRecordConstructedAndParsed");

        String uri1 = "special-protocol://markuspage.com";
        assertEquals("uri1 get", uri1, new URIRecord(uri1).getURI());
        assertEquals("uri1 parsed", uri1, new URIRecord(new URIRecord(uri1).toNDEFRecord().getPayload(), 0).getURI());

        String uri2 = "http://www.markuspage.com";
        assertEquals("uri2", uri2, new URIRecord(new URIRecord(uri2).toNDEFRecord().getPayload(), 0).getURI());

        String uri3 = "mailto:markus@markuspage.com";
        assertEquals("uri3", uri3, new URIRecord(new URIRecord(uri3).toNDEFRecord().getPayload(), 0).getURI());
    }

    private void testURIRecordParsed() throws AssertionFailedException {
        System.out.println("testURIRecordParsed");

        doTestURIAbbrevationParsed("http://www.markuspage.com", 0x00, "http://www.markuspage.com");
        doTestURIAbbrevationParsed("https://www.markuspage.com", 0x00, "https://www.markuspage.com");
        doTestURIAbbrevationParsed("http://markuspage.com", 0x00, "http://markuspage.com");
        doTestURIAbbrevationParsed("https://markuspage.com", 0x00, "https://markuspage.com");
        doTestURIAbbrevationParsed("tel:+46704249485", 0x00, "tel:+46704249485");
        doTestURIAbbrevationParsed("mailto:markus@markuspage.com", 0x00, "mailto:markus@markuspage.com");
        doTestURIAbbrevationParsed("ftp://anonymouse:anonymous@markuspage.com", 0x00, "ftp://anonymouse:anonymous@markuspage.com");
        doTestURIAbbrevationParsed("ftp://ftp.markuspage.com", 0x00, "ftp://ftp.markuspage.com");
        doTestURIAbbrevationParsed("ftps://markuspage.com", 0x00, "ftps://markuspage.com");
        doTestURIAbbrevationParsed("sftp://markuspage.com", 0x00, "sftp://markuspage.com");
        doTestURIAbbrevationParsed("smb://markuspage.com", 0x00, "smb://markuspage.com");
        doTestURIAbbrevationParsed("nfs://markuspage.com", 0x00, "nfs://markuspage.com");
        doTestURIAbbrevationParsed("ftp://markuspage.com", 0x00, "ftp://markuspage.com");
        doTestURIAbbrevationParsed("dav://markuspage.com", 0x00, "dav://markuspage.com");
        doTestURIAbbrevationParsed("news:markuspage.com", 0x00, "news:markuspage.com");
        doTestURIAbbrevationParsed("telnet://markuspage.com", 0x00, "telnet://markuspage.com");
        doTestURIAbbrevationParsed("imap:markuspage.com", 0x00, "imap:markuspage.com");
        doTestURIAbbrevationParsed("rtsp://markuspage.com", 0x00, "rtsp://markuspage.com");
        doTestURIAbbrevationParsed("urn:markuspage.com", 0x00, "urn:markuspage.com");
        doTestURIAbbrevationParsed("pop:markuspage.com", 0x00, "pop:markuspage.com");
        doTestURIAbbrevationParsed("sip:markuspage.com", 0x00, "sip:markuspage.com");
        doTestURIAbbrevationParsed("sips:markuspage.com", 0x00, "sips:markuspage.com");
        doTestURIAbbrevationParsed("tftp:markuspage.com", 0x00, "tftp:markuspage.com");
        doTestURIAbbrevationParsed("btspp://markuspage.com", 0x00, "btspp://markuspage.com");
        doTestURIAbbrevationParsed("btl2cap://markuspage.com", 0x00, "btl2cap://markuspage.com");
        doTestURIAbbrevationParsed("btgoep://markuspage.com", 0x00, "btgoep://markuspage.com");
        doTestURIAbbrevationParsed("tcpobex://markuspage.com", 0x00, "tcpobex://markuspage.com");
        doTestURIAbbrevationParsed("irdaobex://markuspage.com", 0x00, "irdaobex://markuspage.com");
        doTestURIAbbrevationParsed("file://markuspage.com", 0x00, "file://markuspage.com");
        doTestURIAbbrevationParsed("urn:epc:id:markuspage.com", 0x00, "urn:epc:id:markuspage.com");
        doTestURIAbbrevationParsed("urn:epc:tag:markuspage.com", 0x00, "urn:epc:tag:markuspage.com");
        doTestURIAbbrevationParsed("urn:epc:pat:markuspage.com", 0x00, "urn:epc:pat:markuspage.com");
        doTestURIAbbrevationParsed("urn:epc:raw:markuspage.com", 0x00, "urn:epc:raw:markuspage.com");
        doTestURIAbbrevationParsed("urn:epc:markuspage.com", 0x00, "urn:epc:markuspage.com");
        doTestURIAbbrevationParsed("urn:nfc:markuspage.com", 0x00, "urn:nfc:markuspage.com");

        doTestURIAbbrevationParsed("http://www.markuspage.com", 0x01, "markuspage.com");
        doTestURIAbbrevationParsed("https://www.markuspage.com", 0x02, "markuspage.com");
        doTestURIAbbrevationParsed("http://markuspage.com", 0x03, "markuspage.com");
        doTestURIAbbrevationParsed("https://markuspage.com", 0x04, "markuspage.com");
        doTestURIAbbrevationParsed("tel:+46704249485", 0x05, "+46704249485");
        doTestURIAbbrevationParsed("mailto:markus@markuspage.com", 0x06, "markus@markuspage.com");
        doTestURIAbbrevationParsed("ftp://anonymous:anonymous@markuspage.com", 0x07, "markuspage.com");
        doTestURIAbbrevationParsed("ftp://ftp.markuspage.com", 0x08, "markuspage.com");
        doTestURIAbbrevationParsed("ftps://markuspage.com", 0x09, "markuspage.com");
        doTestURIAbbrevationParsed("sftp://markuspage.com", 0x0A, "markuspage.com");
        doTestURIAbbrevationParsed("smb://markuspage.com", 0x0B, "markuspage.com");
        doTestURIAbbrevationParsed("nfs://markuspage.com", 0x0C, "markuspage.com");
        doTestURIAbbrevationParsed("ftp://markuspage.com", 0x0D, "markuspage.com");
        doTestURIAbbrevationParsed("dav://markuspage.com", 0x0E, "markuspage.com");
        doTestURIAbbrevationParsed("news:markuspage.com", 0x0F, "markuspage.com");
        doTestURIAbbrevationParsed("telnet://markuspage.com", 0x10, "markuspage.com");
        doTestURIAbbrevationParsed("imap:markuspage.com", 0x11, "markuspage.com");
        doTestURIAbbrevationParsed("rtsp://markuspage.com", 0x12, "markuspage.com");
        doTestURIAbbrevationParsed("urn:markuspage.com", 0x13, "markuspage.com");
        doTestURIAbbrevationParsed("pop:markuspage.com", 0x14, "markuspage.com");
        doTestURIAbbrevationParsed("sip:markuspage.com", 0x15, "markuspage.com");
        doTestURIAbbrevationParsed("sips:markuspage.com", 0x16, "markuspage.com");
        doTestURIAbbrevationParsed("tftp:markuspage.com", 0x17, "markuspage.com");
        doTestURIAbbrevationParsed("btspp://markuspage.com", 0x18, "markuspage.com");
        doTestURIAbbrevationParsed("btl2cap://markuspage.com", 0x19, "markuspage.com");
        doTestURIAbbrevationParsed("btgoep://markuspage.com", 0x1A, "markuspage.com");
        doTestURIAbbrevationParsed("tcpobex://markuspage.com", 0x1B, "markuspage.com");
        doTestURIAbbrevationParsed("irdaobex://markuspage.com", 0x1C, "markuspage.com");
        doTestURIAbbrevationParsed("file://markuspage.com", 0x1D, "markuspage.com");
        doTestURIAbbrevationParsed("urn:epc:id:markuspage.com", 0x1E, "markuspage.com");
        doTestURIAbbrevationParsed("urn:epc:tag:markuspage.com", 0x1F, "markuspage.com");
        doTestURIAbbrevationParsed("urn:epc:pat:markuspage.com", 0x20, "markuspage.com");
        doTestURIAbbrevationParsed("urn:epc:raw:markuspage.com", 0x21, "markuspage.com");
        doTestURIAbbrevationParsed("urn:epc:markuspage.com", 0x22, "markuspage.com");
        doTestURIAbbrevationParsed("urn:nfc:markuspage.com", 0x23, "markuspage.com");
    }

    private byte[] constructURIRecord(int abbr, String suffix) throws UnsupportedEncodingException {

        byte[] sBytes = suffix.getBytes("utf-8");
        byte[] bytes = new byte[1 + suffix.length()];
        bytes[0] = (byte) abbr;
        System.arraycopy(sBytes, 0, bytes, 1, sBytes.length);

        return bytes;
    }

    private void doTestURIAbbrevationParsed(String url, int abbr, String suffix) throws AssertionFailedException {
        try {
            byte[] bytes = constructURIRecord(abbr, suffix);
            assertEquals(url, new URIRecord(bytes, 0).getURI());
        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
            fail(ex.getMessage());
        }
    }

    private void testURIRecordConstructed() throws AssertionFailedException {
        System.out.println("testURIRecordConstructed");

        doTestURIAbbrevationConstructed("http://www.markuspage.com", 0x01, "markuspage.com");
        doTestURIAbbrevationConstructed("https://www.markuspage.com", 0x02, "markuspage.com");
        doTestURIAbbrevationConstructed("http://markuspage.com", 0x03, "markuspage.com");
        doTestURIAbbrevationConstructed("https://markuspage.com", 0x04, "markuspage.com");
        doTestURIAbbrevationConstructed("tel:+46704249485", 0x05, "+46704249485");
        doTestURIAbbrevationConstructed("mailto:markus@markuspage.com", 0x06, "markus@markuspage.com");
        doTestURIAbbrevationConstructed("ftp://anonymous:anonymous@markuspage.com", 0x07, "markuspage.com");
        doTestURIAbbrevationConstructed("ftp://ftp.markuspage.com", 0x08, "markuspage.com");
        doTestURIAbbrevationConstructed("ftps://markuspage.com", 0x09, "markuspage.com");
        doTestURIAbbrevationConstructed("sftp://markuspage.com", 0x0A, "markuspage.com");
        doTestURIAbbrevationConstructed("smb://markuspage.com", 0x0B, "markuspage.com");
        doTestURIAbbrevationConstructed("nfs://markuspage.com", 0x0C, "markuspage.com");
        doTestURIAbbrevationConstructed("ftp://markuspage.com", 0x0D, "markuspage.com");
        doTestURIAbbrevationConstructed("dav://markuspage.com", 0x0E, "markuspage.com");
        doTestURIAbbrevationConstructed("news:markuspage.com", 0x0F, "markuspage.com");
        doTestURIAbbrevationConstructed("telnet://markuspage.com", 0x10, "markuspage.com");
        doTestURIAbbrevationConstructed("imap:markuspage.com", 0x11, "markuspage.com");
        doTestURIAbbrevationConstructed("rtsp://markuspage.com", 0x12, "markuspage.com");
        doTestURIAbbrevationConstructed("urn:markuspage.com", 0x13, "markuspage.com");
        doTestURIAbbrevationConstructed("pop:markuspage.com", 0x14, "markuspage.com");
        doTestURIAbbrevationConstructed("sip:markuspage.com", 0x15, "markuspage.com");
        doTestURIAbbrevationConstructed("sips:markuspage.com", 0x16, "markuspage.com");
        doTestURIAbbrevationConstructed("tftp:markuspage.com", 0x17, "markuspage.com");
        doTestURIAbbrevationConstructed("btspp://markuspage.com", 0x18, "markuspage.com");
        doTestURIAbbrevationConstructed("btl2cap://markuspage.com", 0x19, "markuspage.com");
        doTestURIAbbrevationConstructed("btgoep://markuspage.com", 0x1A, "markuspage.com");
        doTestURIAbbrevationConstructed("tcpobex://markuspage.com", 0x1B, "markuspage.com");
        doTestURIAbbrevationConstructed("irdaobex://markuspage.com", 0x1C, "markuspage.com");
        doTestURIAbbrevationConstructed("file://markuspage.com", 0x1D, "markuspage.com");
        doTestURIAbbrevationConstructed("urn:epc:id:markuspage.com", 0x1E, "markuspage.com");
        doTestURIAbbrevationConstructed("urn:epc:tag:markuspage.com", 0x1F, "markuspage.com");
        doTestURIAbbrevationConstructed("urn:epc:pat:markuspage.com", 0x20, "markuspage.com");
        doTestURIAbbrevationConstructed("urn:epc:raw:markuspage.com", 0x21, "markuspage.com");
        doTestURIAbbrevationConstructed("urn:epc:markuspage.com", 0x22, "markuspage.com");
        doTestURIAbbrevationConstructed("urn:nfc:markuspage.com", 0x23, "markuspage.com");
    }

    private void doTestURIAbbrevationConstructed(String url, int abbr, String suffix) throws AssertionFailedException {
        try {
            byte[] sBytes = suffix.getBytes("utf-8");
            byte[] expected = new byte[1 + suffix.length()];
            expected[0] = (byte) abbr;
            System.arraycopy(sBytes, 0, expected, 1, sBytes.length);

            byte[] actual = new URIRecord(url).toNDEFRecord().getPayload();

            assertTrue(url + "-" + abbr, Utils.equals(expected, actual));

        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
            fail(ex.getMessage());
        }
    }

    private void testURIRecordEquals() throws AssertionFailedException {
        System.out.println("testURIRecordEquals");
        try {

            URIRecord a1 = new URIRecord("http://www.ericsson.com");
            URIRecord a2 = new URIRecord("http://www.ericsson.com");

            URIRecord b1 = new URIRecord(constructURIRecord(5, "ericsson.com"), 0);
            URIRecord b2 = new URIRecord(constructURIRecord(5, "ericsson.com"), 0);

            SignatureRecord c = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "OTHER-SIGN".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0]));
            SignatureRecord d = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, new URIRecord("http://kth.se")), new CertificateField(CertificateField.X509, new CertificateBytes[0]));
            SignatureRecord e = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[]{new CertificateBytes(new byte[]{0xA})}));
            SignatureRecord f = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0], new URIRecord("http://kth.se")));

            assertEquals("a1 == a2", a1, a2);
            assertEquals("a1 h== a2", a1.hashCode(), a2.hashCode());

            assertEquals("b1 == b2", b1, b2);
            assertEquals("b1 h== b2", b1.hashCode(), b2.hashCode());

            assertNotEquals("a1 != b1", a1, b1);
            assertNotEquals("a1 != c", a1, c);
            assertNotEquals("a1 != d", a1, d);
            assertNotEquals("a1 != e", a1, e);
            assertNotEquals("a1 != f", a1, f);
            assertNotEquals("b1 != c", b1, c);
            assertNotEquals("b1 != d", b1, d);
            assertNotEquals("b1 != e", b1, e);
            assertNotEquals("b1 != f", b1, f);

        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
            fail(ex.getMessage());
        }
    }

    private void testSignatureRecordEquals() throws AssertionFailedException {
        System.out.println("testSignatureRecordEquals");

        SignatureRecord a1 = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0]));
        SignatureRecord a2 = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0]));

        //TODO with other signType: SignatureRecord b = new SignatureRecord(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes(), null, CertificateField.X509, new Certificate[0], null);
        SignatureRecord c = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "OTHER-SIGN".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0], null));

        SignatureRecord d = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, new URIRecord("http://kth.se")), new CertificateField(CertificateField.X509, new CertificateBytes[0]));

        SignatureRecord e = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[]{new CertificateBytes(new byte[]{0xA})}, null));
        SignatureRecord f = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0], new URIRecord("http://kth.se")));


        assertEquals("a1 == a2", a1, a2);
        assertEquals("a1 h== a2", a1.hashCode(), a2.hashCode());

        //TODO assertNotEquals("a1 != b", a1, b);
        assertNotEquals("a1 != c", a1, c);
        assertNotEquals("a1 != d", a1, d);
        assertNotEquals("a1 != e", a1, e);
        assertNotEquals("a1 != f", a1, f);
    }

    private void testCreateSignaturRecordWithURIs() throws AssertionFailedException {
        System.out.println("testCreateSignaturRecordWithURIs");

        try {

            SignatureRecord withSignUri = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, new URIRecord("http://kth.se")), new CertificateField(CertificateField.X509, new CertificateBytes[0]));
        } catch (IllegalArgumentException ex) {
            fail("withSignUri: " + ex.getMessage());
        }

        try {

            SignatureRecord withCertUri = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, new URIRecord("http://kth.se")), new CertificateField(CertificateField.X509, new CertificateBytes[0], new URIRecord("http://kth.se")));
        } catch (IllegalArgumentException ex) {
            fail("withSignUri: " + ex.getMessage());
        }

        try {

            SignatureRecord withBoth = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0], new URIRecord("http://kth.se")));
        } catch(IllegalArgumentException ex) {
            fail("withSignUri: " + ex.getMessage());
        }

        try {
            SignatureRecord withoutSign = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, (byte[])null), new CertificateField(CertificateField.X509, new CertificateBytes[0], new URIRecord("http://kth.se")));

            fail("withoutSign should be invalid");
        } catch (IllegalArgumentException ex) {} // OK

//        try {
//            SignatureRecord withoutCert = new SignatureRecord(SignatureField.RSASSA_PSS, null, new URIRecord("http://kth.se"), CertificateField.X509, new CertificateBytes[0], null);
//
//            fail("withoutCert should be invalid");
//        } catch (IllegalArgumentException ex) {} // OK

        try {
            SignatureRecord withoutBoth = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, (byte[])null), new CertificateField(CertificateField.X509, null, null));

            fail("withoutBoth should be invalid");
        } catch (IllegalArgumentException ex) {} // OK

    }

    /**
     * 25
     */
    private void testGetSignatureURIConstructedAndParsed() throws AssertionFailedException {

        System.out.println("testGetSignatureURIConstructedAndParsed");

        URIRecord uri1 = new URIRecord("http://kth.se");
        byte[] sign = "SIGNATURE".getBytes();

        try {
            SignatureRecord withSignUri = new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, uri1), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord());

            assertEquals("withSignUri.getSigUri()", uri1, withSignUri.getSignatureField().getUri());
            assertTrue("withSignUri.getSig() == null", null == withSignUri.getSignatureField().getSignature());

        } catch (InvalidSignatureRecord ex) {
            fail("withSignUri: " + ex.getMessage());
        } catch (IllegalArgumentException ex) {
            fail("withSignUri: " + ex.getMessage());
        }

        try {
            SignatureRecord withSign = new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sign), new CertificateField(CertificateField.X509, new CertificateBytes[0])).toNDEFRecord());


            assertTrue("withSignUri.getSig() == SIGNATURE", Utils.equals(sign, withSign.getSignatureField().getSignature()));
            assertTrue("withSignUri.getSigUri() == null", null == withSign.getSignatureField().getUri());

        } catch (InvalidSignatureRecord ex) {
            fail("withSignUri: " + ex.getMessage());
        } catch (IllegalArgumentException ex) {
            fail("withSignUri: " + ex.getMessage());
        }


    }

    private void testGetCertificatesConstructedAndParsed() throws AssertionFailedException {
        try {
            System.out.println("testGetCertificatesConstructedAndParsed");

            String sig0 = "";
            String sig1 = "S";
            String sig2 = "Signature 2";
            String sig3 = "Signature 333333333333333333333333333333333333333333333.";

            CertificateBytes cert0 = new CertificateBytes(new byte[]{0xa,0xb,0xc});
            CertificateBytes cert1 = new CertificateBytes(new byte[]{0x0,0x1,0x2});
            CertificateBytes cert2 = new CertificateBytes(new byte[]{0x3,0x4,0x5});


            assertEquals("Signature 0", cert0, new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig0.getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[]{cert0})).toNDEFRecord()).getCertificateField().getChain()[0]);
            assertEquals("Signature 1-0", cert0, new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig1.getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[]{cert0, cert1,cert2})).toNDEFRecord()).getCertificateField().getChain()[0]);
            assertEquals("Signature 1-1", cert1, new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig1.getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[]{cert0, cert1,cert2})).toNDEFRecord()).getCertificateField().getChain()[1]);
            assertEquals("Signature 1-2", cert2, new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig1.getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[]{cert0, cert1,cert2})).toNDEFRecord()).getCertificateField().getChain()[2]);

            CertificateBytes certLong = new CertificateBytes(new byte[750]);
            assertEquals("Signature Long", certLong, new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig0.getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[]{certLong})).toNDEFRecord()).getCertificateField().getChain()[0]);

            CertificateBytes certLonger = new CertificateBytes(new byte[768]);
            assertEquals("Signature Longer", certLonger, new SignatureRecord(new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, sig0.getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[]{certLonger})).toNDEFRecord()).getCertificateField().getChain()[0]);

        } catch (InvalidSignatureRecord ex) {
            ex.printStackTrace();
            fail(ex.getMessage());
        }
    }

    private void testParseNDEF() throws AssertionFailedException {
        System.out.println("testParseNDEF");

        try {
            NDEFMessage msg = new NDEFMessage(TestData.msgSpUrlSig1, 0);
            System.out.println("Number of records: "+msg.getNumberOfRecords());
        } catch(IllegalArgumentException ex) {
            fail("parse NDEF: " + ex.getMessage());
        }
    }

    private void testDontIgnoreRFUForExternalRTD() throws AssertionFailedException {
        System.out.println("testDontIgnoreRFUForExternalRTD");

        // Construct
        try {
            SignatureRecord r1 = new SignatureRecord(new SignatureField(0x05, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0]));
            NDEFRecord record = r1.toNDEFRecord(EXTERNAL_SIGREC, new byte[0]);
//            Utils.dumpAsJavaByteArray(record.toByteArray());
        } catch(Exception ex) {
            fail("Did not accept external RTD sig rec");
        }

        try {
            SignatureRecord r2 = new SignatureRecord(new SignatureField(0x11, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0]));
            NDEFRecord record = r2.toNDEFRecord(EXTERNAL_SIGREC, new byte[0]);
        } catch(Exception ex) {
            fail("Did not accept external RTD sig rec");
        }

        try {
            SignatureRecord r3 = new SignatureRecord(new SignatureField(0x7f, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0]));
            NDEFRecord record = r3.toNDEFRecord(EXTERNAL_SIGREC, new byte[0]);
        } catch(Exception ex) {
            fail("Did not accept external RTD sig rec");
        }

        try {
            SignatureRecord r4 = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(0x02, new CertificateBytes[0]));
            NDEFRecord record = r4.toNDEFRecord(EXTERNAL_SIGREC, new byte[0]);
        } catch(Exception ex) {
            fail("Did not accept external RTD sig rec");
        }
        try {
            SignatureRecord r5 = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(0x05, new CertificateBytes[0]));
            NDEFRecord record = r5.toNDEFRecord(EXTERNAL_SIGREC, new byte[0]);
        } catch(Exception ex) {
            fail("Did not accept external RTD sig rec");
        }
        try {
            SignatureRecord r6 = new SignatureRecord(new SignatureField(SignatureField.RSASSA_PSS, "SIGNATURE".getBytes()), new CertificateField(0x07, new CertificateBytes[0]));
            NDEFRecord record = r6.toNDEFRecord(EXTERNAL_SIGREC, new byte[0]);
        } catch(Exception ex) {
            fail("Did not accept external RTD sig rec");
        }
        try {
            SignatureRecord r7 = new SignatureRecord(new SignatureField(0x14, "SIGNATURE".getBytes()), new CertificateField(0x06, new CertificateBytes[0]));
            NDEFRecord record = r7.toNDEFRecord(EXTERNAL_SIGREC, new byte[0]);
        } catch(Exception ex) {
            fail("Did not accept external RTD sig rec");
        }

        // Parse
        try {
            byte[] bytes = new byte[TestData.recSigExternal1.length];
            System.arraycopy(TestData.recSigExternal1, 0, bytes, 0, TestData.recSigExternal1.length);
            bytes[27] &= 0x80;
            bytes[27] |= 0x05; // signatureType
            SignatureRecord r1 = new SignatureRecord(new NDEFRecord(bytes, 0));
            
        } catch(InvalidSignatureRecord ex) {
            fail("Should have accepted r1 c");
        }

        try {
            byte[] bytes = new byte[TestData.recSigExternal1.length];
            System.arraycopy(TestData.recSigExternal1, 0, bytes, 0, TestData.recSigExternal1.length);
            bytes[27] &= 0x80;
            bytes[27] |= 0x11;  // signatureType
            SignatureRecord r1 = new SignatureRecord(new NDEFRecord(bytes, 0));
        } catch(InvalidSignatureRecord ex) {
            fail("Should have Accepted r2 c");
        }

        try {
            byte[] bytes = new byte[TestData.recSigExternal1.length];
            System.arraycopy(TestData.recSigExternal1, 0, bytes, 0, TestData.recSigExternal1.length);
            bytes[27] &= 0x80;
            bytes[27] |= 0x7f;  // signatureType
            SignatureRecord r1 = new SignatureRecord(new NDEFRecord(bytes, 0));

        } catch(InvalidSignatureRecord ex) {
            fail("should Accepted r3 c");
        }

        try {
            byte[] bytes = new byte[TestData.recSigExternal1.length];
            System.arraycopy(TestData.recSigExternal1, 0, bytes, 0, TestData.recSigExternal1.length);
            bytes[39] &= 0x70;
            bytes[39] |= (0x02 << 4);
            SignatureRecord r1 = new SignatureRecord(new NDEFRecord(bytes, 0));
            
        } catch(InvalidSignatureRecord ex) {
            fail("should Accepted r4 c");
        }
        try {
            byte[] bytes = new byte[TestData.recSigExternal1.length];
            System.arraycopy(TestData.recSigExternal1, 0, bytes, 0, TestData.recSigExternal1.length);
            bytes[39] &= 0x70;
            bytes[39] |= (0x05 << 4);
            SignatureRecord r1 = new SignatureRecord(new NDEFRecord(bytes, 0));
        } catch(InvalidSignatureRecord ex) {
            fail("should Accepted r5 c");
        }
        try {
            byte[] bytes = new byte[TestData.recSigExternal1.length];
            System.arraycopy(TestData.recSigExternal1, 0, bytes, 0, TestData.recSigExternal1.length);
            bytes[39] &= 0x70;
            bytes[39] |= (0x07 << 4);
            SignatureRecord r1 = new SignatureRecord(new NDEFRecord(bytes, 0));
        } catch(InvalidSignatureRecord ex) {
            fail("should Accepted r6 c");
        }
        try {
            byte[] bytes = new byte[TestData.recSigExternal1.length];
            System.arraycopy(TestData.recSigExternal1, 0, bytes, 0, TestData.recSigExternal1.length);
            bytes[27] &= 0x80;
            bytes[27] |= 0x14;
            bytes[39] &= 0x70;
            bytes[39] |= (0x06 << 4);
            SignatureRecord r1 = new SignatureRecord(new NDEFRecord(bytes, 0));
        } catch(InvalidSignatureRecord ex) {
            fail("should Accepted r7 b");
        }

    }

    private void testToNDEFRecordWithExternalType() throws AssertionFailedException {
        System.out.println("testToNDEFRecordWithExternalType");

        SignatureRecord r1 = new SignatureRecord(new SignatureField(0x05, "SIGNATURE".getBytes()), new CertificateField(CertificateField.X509, new CertificateBytes[0]));
        NDEFRecord record = r1.toNDEFRecord(EXTERNAL_SIGREC, new byte[0]);
        assertEquals("record before", EXTERNAL_SIGREC, record.getRecordType());
        NDEFRecord r2 = new NDEFRecord(record.toByteArray(), 0);
        assertEquals("after loaded", EXTERNAL_SIGREC, r2.getRecordType());
    }

}
